﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;

namespace YJKRoom.SpaceRoomNameCreation
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	public class CmdSpaceRoomNameCreation : IExternalCommand
	{
		public Result Execute(ExternalCommandData cmdData, ref string messages, ElementSet elements)
		{
			Document document = cmdData.Application.ActiveUIDocument.Document;
			Selection selection = cmdData.Application.ActiveUIDocument.Selection;
			IList<Element> list = null;
            Assist.RoomFilter roomFilter = new Assist.RoomFilter();
			try
			{
				do
				{
					list = selection.PickElementsByRectangle(roomFilter, "请框选房间");
				}
				while (list.Count <= 0);
			}
			catch
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			List<Room> list2 = new List<Room>();
			foreach (Element element in list)
			{
				list2.Add(element as Room);
			}
			List<string> allParameters = this.GetAllParameters(list2[0]);
			List<ModelTextType> allFontType = this.GetAllFontType(document);
			SpaceRoomNameCreationForm spaceRoomNameCreationForm = new SpaceRoomNameCreationForm(allParameters, allFontType);
			if (DialogResult.OK == spaceRoomNameCreationForm.ShowDialog())
			{
				int selIndexFontType = spaceRoomNameCreationForm.GetSelIndexFontType();
				List<string> selRoomParaNames = spaceRoomNameCreationForm.GetSelRoomParaNames();
				Transaction transaction = new Transaction(document, "CreateRoomName");
				transaction.Start();
				foreach (Room room in list2)
				{
					string roomName = this.ReplaceParaNames(selRoomParaNames, room);
					LocationPoint locationPoint = room.Location as LocationPoint;
					this.CreateRoomName(cmdData.Application, locationPoint.Point, roomName, allFontType[selIndexFontType]);
				}
				transaction.Commit();
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void CreateRoomName(UIApplication uiApp, XYZ pt, string roomName, ModelTextType noteType)
		{
			Document document = uiApp.ActiveUIDocument.Document;
			ICollection<Element> collection = new FilteredElementCollector(document).OfClass(typeof(ModelText)).ToElements();
			XYZ xyz = new XYZ(pt.X, pt.Y, document.ActiveView.GenLevel.Elevation);
			if (collection.Count > 0)
			{
				ModelText modelText = collection.ElementAt(0) as ModelText;
				ICollection<ElementId> source = ElementTransformUtils.CopyElement(uiApp.ActiveUIDocument.Document, modelText.Id, xyz);
				ModelText modelText2 = document.GetElement(source.ElementAt(0)) as ModelText;
				LocationPoint locationPoint = modelText2.Location as LocationPoint;
				locationPoint.Point = xyz;
				modelText2.Text = roomName;
				modelText2.ModelTextType = noteType;
				document.Regenerate();
				return;
			}
			if (collection.Count == 0)
			{
				string versionNumber = uiApp.Application.VersionNumber;
				string text = AssistFunc.GetAppRootPath() + "\\Templates\\" + versionNumber + "\\ScrTemplate.rvt";
				Document document2 = uiApp.Application.OpenDocumentFile(text);
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document2);
				collection = filteredElementCollector.OfClass(typeof(ModelText)).ToElements();
				ModelText modelText3 = null;
				IEnumerator<Element> enumerator = collection.GetEnumerator();
				{
					if (enumerator.MoveNext())
					{
						Element element = enumerator.Current;
						modelText3 = (element as ModelText);
					}
				}
				List<ElementId> list = new List<ElementId>();
				list.Add(modelText3.Id);
				CopyPasteOptions copyPasteOptions = new CopyPasteOptions();
				copyPasteOptions.SetDuplicateTypeNamesHandler(new HideAndAcceptDuplicateTypeNamesHandler());
				ICollection<ElementId> source2 = ElementTransformUtils.CopyElements(document2, list, document, Transform.Identity, copyPasteOptions);
				ModelText modelText4 = document.GetElement(source2.ElementAt(0)) as ModelText;
				LocationPoint locationPoint2 = modelText4.Location as LocationPoint;
				locationPoint2.Point = xyz;
				modelText4.Text = roomName;
				modelText4.ModelTextType = noteType;
			}
		}

		private List<string> GetAllParameters(Room room)
		{
			List<string> list = new List<string>();
			foreach (object obj in room.Parameters)
			{
				Parameter parameter = (Parameter)obj;
				list.Add(parameter.Definition.Name);
			}
			return list;
		}

		private List<ModelTextType> GetAllFontType(Autodesk.Revit.DB.Document doc)
		{
			List<ModelTextType> list = new List<ModelTextType>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(ModelTextType));
			if (filteredElementCollector != null)
			{
				IList<Element> list2 = filteredElementCollector.ToElements();
				foreach (Element element in list2)
				{
					list.Add(element as ModelTextType);
				}
			}
			return list;
		}

		private string ReplaceParaNames(List<string> names, Room room)
		{
			string text = "";
			foreach (string text2 in names)
			{
				int startIndex = 0;
				string text3 = text2;
				for (;;)
				{
					int num = text3.IndexOf('[', startIndex);
					if (-1 == num)
					{
						break;
					}
					int num2 = text3.IndexOf(']', num);
					if (-1 == num2)
					{
						break;
					}
					string paraName = text3.Substring(num + 1, num2 - num - 1);
					string paraValue = this.GetParaValue(paraName, room);
					string oldValue = text3.Substring(num, num2 - num + 1);
					text3 = text3.Replace(oldValue, paraValue);
				}
				text = text + text3 + "\r\n";
			}
			return text;
		}

		private string GetParaValue(string paraName, Room room)
		{
			foreach (object obj in room.Parameters)
			{
				Parameter parameter = (Parameter)obj;
				if (parameter.Definition.Name == paraName)
				{
					double num = 0.0;
                    switch ((int)parameter.StorageType)
					{
					case 1:
						num = AssistFunc.feetToMM((double)parameter.AsInteger());
						return Math.Round(num, 2).ToString();
					case 2:
						if (paraName.Contains("周长") || paraName.Contains("偏移"))
						{
							num = AssistFunc.feetToMM(parameter.AsDouble()) / 1000.0;
						}
						else if (paraName == "面积" || paraName == "人均面积")
						{
							num = AssistFunc.feetToMM(parameter.AsDouble()) / 1000.0;
							num = AssistFunc.feetToMM(num) / 1000.0;
						}
						return Math.Round(num, 2).ToString();
					case 3:
						return parameter.AsString();
					case 4:
						return parameter.AsValueString();
					}
				}
			}
			return null;
		}
	}
}
